﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Common
{
    /// <summary>
    /// 百度翻译
    /// </summary>
    public class BaiduFanYi
    {
        private static Dictionary<string, string> history = new Dictionary<string, string>();
        private readonly HttpClient client = new HttpClient();
        private readonly Random random = new Random();
        private readonly string _path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "history.json");

        private readonly string _appId;
        private readonly string _key;
        private readonly string _from;
        private readonly string _to;
        private readonly int _delay;

        /// <summary>
        /// 百度翻译
        /// </summary>
        /// <param name="appId">百度翻译应用ID</param>
        /// <param name="key">百度翻译应用密钥</param>
        /// <param name="from">翻译源语言</param>
        /// <param name="to">译文语言</param>
        /// <param name="delay">延迟时间 毫秒</param>
        public BaiduFanYi(string appId, string key, string from = "en", string to = "zh", int delay = 1000)
        {
            _appId = appId;
            _key = key;
            _from = from;
            _to = to;
            _delay = delay;
            if (File.Exists(_path))
            {
                var json = File.ReadAllText(_path);
                history = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
            }
        }

        /// <summary>
        /// 保存历史翻译
        /// </summary>
        public void Save()
        {
            var json = JsonConvert.SerializeObject(history);
            File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "history.json"), json);
        }

        /// <summary>
        /// 获取翻译
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public string Render(string query)
        {
            if (string.IsNullOrWhiteSpace(query))
            {
                return query;
            }

            if (history.Keys.Any(t => t == query))
            {
                return history[query].Replace("“", "'").Replace("”", "'").Replace("；", ";").Replace("（", "(").Replace("）", ")").Replace("，", ",");
            }

            string salt = random.Next(100000).ToString();
            string text = UrlEncode(query);
            var sign = EncryptString($"{_appId}{query}{salt}{_key}");
            var resp = client.GetStringAsync($"http://api.fanyi.baidu.com/api/trans/vip/translate?q={text}&from={_from}&to={_to}&appid={_appId}&salt={salt}&sign={sign}").Result;
            var json = JObject.Parse(resp);

            if (json.ContainsKey("error_code"))
            {
                throw new Exception($"百度翻译错误代码：{json["error_code"]}");
            }

            var result = json["trans_result"][0]["dst"].ToString()?.Replace("“", "'").Replace("”", "'").Replace("；", ";").Replace("（", "(").Replace("）", ")").Replace("，", ",");
            history.Add(query, result);
            Task.Delay(_delay).Wait();
            return result;
        }

        /// <summary>
        /// UrlEncode (URL编码)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private string UrlEncode(string str)
        {
            StringBuilder sb = new StringBuilder();
            byte[] byStr = Encoding.UTF8.GetBytes(str);
            for (int i = 0; i < byStr.Length; i++)
            {
                sb.Append(@"%" + Convert.ToString(byStr[i], 16));
            }
            return (sb.ToString());
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public string EncryptString(string str)
        {
            MD5 md5 = MD5.Create();
            // 将字符串转换成字节数组
            byte[] byteOld = Encoding.UTF8.GetBytes(str);
            // 调用加密方法
            byte[] byteNew = md5.ComputeHash(byteOld);
            // 将加密结果转换为字符串
            StringBuilder sb = new StringBuilder();
            foreach (byte b in byteNew)
            {
                // 将字节转换成16进制表示的字符串，
                sb.Append(b.ToString("x2"));
            }
            // 返回加密的字符串
            return sb.ToString();
        }
    }
}
